using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.IO;
using Infrastructure.WebApi;
using Infrastructure.Extensions;

namespace Infrastructure
{
    /// <summary>
    /// HTTP请求辅助类
    /// </summary>
    public static class HttpHelper
    {
        /// <summary>
        /// 发送HTTP请求
        /// </summary>
        /// <param name="addr">Http请求地址</param>
        /// <param name="method">执行的HTTP方法名称</param>
        /// <param name="data">向请求地址发送的数据。</param>
        /// <param name="headers">设置的Http标头,如无特殊设置,可为空。</param>
        /// <param name="reponseHeaders">设置的接收返回的headers  ref Dictionary<string, string> reponseHeaders </param>
        /// <returns>请求执行的结果</returns>
        public static string SendRequest(string addr, string method, string data, WebHeaderCollection headers = null)
        {
            string result = string.Empty;

            //使用回调的方式对证书进行自定义验证
            //合法证书可不采用此方式，直接采用默认验证
            // WebClient进行SSL证书验证，默认不启用
            //ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);

            using (WebClient client = new NewWebClient())
            {
                // 发送HTTP请求
                try
                {

                    if (headers == null)
                    {
                        headers = new WebHeaderCollection();
                    }
                    if (string.IsNullOrEmpty(headers.Get("Content-Type")))
                    {
                        headers.Add("Content-Type:application/json");
                    }
                    // 设置HTTP标头
                    client.Headers = headers;


                    //解析参数 Get
                    if (method.ToUpper() == "GET")
                    {
                        var parms = string.Empty;
                        //反序列化
                        var msg = ConvertJsonExtension.DeserializeObject(Convert.ToString(data), out Dictionary<string, string> format);
                        if (msg == "OK")
                        {
                            foreach (var item in format)
                            {
                                parms += $"{(string.IsNullOrEmpty(parms) ? "?" : "&")}{item.Key}={item.Value}";
                            }
                        }
                        else if (data.IndexOf("?") >= 0 || data.IndexOf("&") >= 0)
                        {
                            if (data.IndexOf("?") != 0)
                            {
                                parms = "?" + data;
                            }
                        }

                        addr += parms;
                    }

                    Uri uri = new Uri(addr);

                    switch (method.ToUpper())
                    {
                        case "GET":
                            result = client.DownloadString(uri);
                            break;
                        case "POST":
                            result = client.UploadString(uri, "POST", data);
                            break;
                        case "PUT":
                            result = client.UploadString(uri, "PUT", data);
                            break;
                        case "DELETE":
                            result = client.UploadString(uri, "DELETE", data);
                            break;
                        default:
                            result = client.UploadString(uri, "POST", data);
                            break;
                    }

                    ////获取返回header信息
                    //if (reponseHeaders.Count > 0)
                    //{
                    //    var setHeaders = new Dictionary<string, string>();
                    //    //var rpHeaders = client.ResponseHeaders;
                    //    foreach (var item in reponseHeaders)
                    //    {
                    //        setHeaders.Add(item.Key, headers.Get(item.Key));
                    //    }
                    //    reponseHeaders = setHeaders;
                    //}
                }
                catch (WebException ex) //请求失败
                {
                    // 获得服务的响应信息
                    if (ex.Response != null && ex.Response.ContentLength > 0)
                    {
                        System.IO.Stream responseStream = ex.Response.GetResponseStream();

                        System.IO.StreamReader reader = new System.IO.StreamReader(responseStream, System.Text.Encoding.UTF8);

                        result = reader.ReadToEnd();
                    }
                    else
                    {
                        result = ex.Message;
                    }

                    throw new Exception(result);
                }
                catch (Exception ex)
                {
                    result = ex.Message;
                    throw new Exception(result);
                }
            }

            return result;
        }

        /// <summary>
        /// 发送文件操作相关的HTTP请求
        /// </summary>
        /// <param name="addr">Http请求地址</param>
        /// <param name="method">执行的HTTP方法名称</param>
        /// <param name="path">上传文件时(POST)，此参数为需要上传的文件的路径。
        /// 下载文件时(GET)，为文件的保存路径。
        /// 删除文件时此参数无实际用处。</param>
        /// <param name="headers">设置的Http标头</param>
        /// <returns>请求执行的结果</returns>
        public static string File(string addr, string method, string path, WebHeaderCollection headers)
        {
            string result = string.Empty;
            byte[] response = null;

            //使用回调的方式对证书进行自定义验证
            //合法证书可不采用此方式，直接采用默认验证
            // WebClient进行SSL证书验证，默认不启用
            //ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);

            using (WebClient client = new WebClient())
            {
                // 发送HTTP请求
                try
                {
                    // 设置HTTP标头
                    client.Headers = headers;

                    Uri uri = new Uri(addr);

                    switch (method.ToUpper())
                    {
                        case "GET":
                            // 打开连接
                            Stream stream = client.OpenRead(uri);

                            // 获得Content-Type
                            string contentType = string.Empty;

                            if (client.ResponseHeaders.AllKeys.Contains("Content-Type"))
                                contentType = client.ResponseHeaders["Content-Type"];

                            // json内容说明是执行信息，直接获取文本信息
                            if (contentType.Contains("json"))
                            {
                                StreamReader reader = new StreamReader(stream);
                                result = reader.ReadToEnd();
                                reader.Dispose();
                            }
                            else // 否则为文件流
                            {
                                int bufferSize = 1024000;

                                byte[] buffer = new byte[bufferSize];
                                int leftBufferSpace = bufferSize;
                                int offset = 0;
                                int appendCount = 0;

                                while (leftBufferSpace >= 0)
                                {
                                    // 缓存已满，将内容追加到文件并重置缓存
                                    if (leftBufferSpace == 0)
                                    {
                                        // 保存文件
                                        // 初次保存时创建(覆盖)文件，之后追加文件
                                        if (appendCount == 0)
                                            FileHelper.SaveFile(path, buffer);
                                        else
                                            FileHelper.AppendFile(path, buffer);

                                        // 更新文件追加次数
                                        appendCount += 1;

                                        // 重置缓存
                                        leftBufferSpace = bufferSize;
                                        offset = 0;
                                        buffer = new byte[bufferSize];
                                    }

                                    int count = stream.Read(buffer, offset, leftBufferSpace);
                                    if (count == 0)
                                        break;

                                    offset += count;
                                    leftBufferSpace -= count;
                                }

                                // 未追加过文件，说明缓存容量足以保存文件全部内容，这里执行文件保存
                                if (appendCount == 0)
                                {
                                    // offset为实际的文件长度
                                    byte[] fileBytes = buffer.Take(offset).ToArray();

                                    // 保存文件
                                    FileHelper.SaveFile(path, fileBytes);
                                }

                                result = ResultHelper.Get(200).Serialize();
                            }
                            stream.Dispose();

                            break;
                        case "POST":
                            response = client.UploadFile(uri, "POST", path);
                            result = Encoding.UTF8.GetString(response);
                            break;
                        case "DELETE":
                            result = client.UploadString(uri, "DELETE", string.Empty);
                            break;
                        default:
                            response = client.UploadFile(uri, "POST", path);
                            result = Encoding.UTF8.GetString(response);
                            break;
                    }
                }
                catch (WebException ex) //请求失败
                {
                    // 获得服务的响应信息
                    if (ex.Response != null && ex.Response.ContentLength > 0)
                    {
                        System.IO.Stream responseStream = ex.Response.GetResponseStream();

                        System.IO.StreamReader reader = new System.IO.StreamReader(responseStream, System.Text.Encoding.UTF8);

                        result = reader.ReadToEnd();
                    }
                    else
                    {
                        result = ex.Message;
                    }

                    throw new Exception(result);
                }
                catch (Exception ex)
                {
                    result = ex.Message;
                    throw new Exception(result);
                }
            }

            return result;
        }

        /// <summary>
        /// 提交数据的HTTP请求
        /// </summary>
        /// <param name="addr">Http请求地址</param>
        /// <param name="method">执行的HTTP方法名称</param>
        /// <param name="data">上传的数据。</param>
        /// <param name="headers">设置的Http标头</param>
        /// <returns>请求执行的结果</returns>
        public static string Data(string addr, string method, byte[] data, WebHeaderCollection headers)
        {
            string result = string.Empty;
            byte[] response = null;

            //使用回调的方式对证书进行自定义验证
            //合法证书可不采用此方式，直接采用默认验证
            // WebClient进行SSL证书验证，默认不启用
            //ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);

            using (WebClient client = new WebClient())
            {
                // 发送HTTP请求
                try
                {
                    // 设置HTTP标头
                    client.Headers = headers;

                    Uri uri = new Uri(addr);

                    response = client.UploadData(uri, method, data);
                    result = Encoding.UTF8.GetString(response);
                }
                catch (WebException ex) //请求失败
                {
                    // 获得服务的响应信息
                    if (ex.Response != null && ex.Response.ContentLength > 0)
                    {
                        System.IO.Stream responseStream = ex.Response.GetResponseStream();

                        System.IO.StreamReader reader = new System.IO.StreamReader(responseStream, System.Text.Encoding.UTF8);

                        result = reader.ReadToEnd();
                    }
                    else
                    {
                        result = ex.Message;
                    }

                    throw new Exception(result);
                }
                catch (Exception ex)
                {
                    result = ex.Message;
                    throw new Exception(result);
                }
            }

            return result;
        }

    }


    /// <summary>
    /// 为WebClient增加超时时间
    /// <para>从WebClient派生一个新的类，重载GetWebRequest方法</para>
    /// </summary>
    public class NewWebClient : WebClient
    {
        public int _timeout { get; set; }

        /// <summary>
        /// 超时时间(毫秒)
        /// </summary>
        public int Timeout
        {
            get
            {
                return _timeout;
            }
            set
            {
                _timeout = value;
            }
        }

        public NewWebClient()
        {
            var timeout = Config.ReadSetting("TimeOut");
            if (string.IsNullOrEmpty(timeout))
            {
                this._timeout = 6000;
            }
            else
            {
                this._timeout = timeout.ToInt(6000);
            }
        }

        public NewWebClient(int timeout)
        {
            this._timeout = timeout;
        }

        protected override WebRequest GetWebRequest(Uri address)
        {
            var result = base.GetWebRequest(address);
            result.Timeout = this._timeout;
            return result;
        }
    }
}
